This fixes a bug whereby foreign pages were freed by the unpin, which
then become owned by the local domain before it destroys its ptes.
It therefore (erroneously) detects the mappings as local and so
updates reference counts, leading to crashes.
Signed-off-by: Keir Fraser <keir@xensource.com>
init_MUTEX(&mm->context.sem);
mm->context.size = 0;
+ mm->context.has_foreign_mappings = 0;
old_mm = current->mm;
if (old_mm && old_mm->context.size > 0) {
down(&old_mm->context.sem);
if (domid == DOMID_SELF)
return -EINVAL;
+ vma->vm_mm->context.has_foreign_mappings = 1;
+
return __direct_remap_pfn_range(
vma->vm_mm, address, mfn, size, prot, domid);
}
task_unlock(tsk);
if (test_bit(PG_pinned, &virt_to_page(mm->pgd)->flags) &&
- (atomic_read(&mm->mm_count) == 1))
+ (atomic_read(&mm->mm_count) == 1) &&
+ !mm->context.has_foreign_mappings)
mm_unpin(mm);
}
task_unlock(tsk);
- if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) )
+ if ( mm->context.pinned && (atomic_read(&mm->mm_count) == 1) &&
+ !mm->context.has_foreign_mappings )
mm_unpin(mm);
}
int size;
struct semaphore sem;
void *ldt;
+#ifdef CONFIG_XEN
+ int has_foreign_mappings;
+#endif
} mm_context_t;
/* mm/memory.c:exit_mmap hook */
struct semaphore sem;
#ifdef CONFIG_XEN
unsigned pinned:1;
+ unsigned has_foreign_mappings:1;
struct list_head unpinned;
#endif
} mm_context_t;